/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.rs.manager.impl;

import com.xy.biz.rs.dao.RecordTemplateDao;
import com.xy.biz.rs.dao.RecordTemplateGroupDao;
import com.xy.biz.rs.dao.RecordTemplateItemDao;
import com.xy.biz.rs.domain.bo.RecordTemplateBO;
import com.xy.biz.rs.domain.bo.RecordTemplateGroupBO;
import com.xy.biz.rs.domain.bo.RecordTemplateItemBO;
import com.xy.biz.rs.domain.converter.RecordTemplateConverter;
import com.xy.biz.rs.domain.converter.RecordTemplateGroupConverter;
import com.xy.biz.rs.domain.converter.RecordTemplateItemConverter;
import com.xy.biz.rs.domain.po.RecordTemplateGroupPO;
import com.xy.biz.rs.domain.po.RecordTemplatePO;
import com.xy.biz.rs.domain.query.RecordTemplateByIdQuery;
import com.xy.biz.rs.domain.query.RecordTemplateQuery;
import com.xy.biz.rs.manager.RecordTemplateManager;
import com.xy.lang.domain.tuples.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author zsp
 * @date 2022-1-4
 */
@Service
public class RecordTemplateManagerImpl implements RecordTemplateManager {

    @Autowired
    private RecordTemplateDao recordTemplateDao;
    @Autowired
    private RecordTemplateGroupDao recordTemplateGroupDao;
    @Autowired
    private RecordTemplateItemDao recordTemplateItemDao;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int saveRecordTemplate(RecordTemplateBO recordTemplateBO) {
        RecordTemplatePO recordTemplatePO = RecordTemplateConverter.toPO(recordTemplateBO);
        int row = recordTemplateDao.saveRecordTemplate(recordTemplatePO);
        if (row > 0) {
            List<RecordTemplateGroupBO> groupList = recordTemplateBO.getGroupList();
            if (!CollectionUtils.isEmpty(groupList)) {
                groupList.forEach(e -> e.setRecordTemplateId(recordTemplatePO.getRecordTemplateId()));
                List<RecordTemplateGroupPO> recordTemplateGroupPOList = RecordTemplateGroupConverter.toPO(groupList);
                row += recordTemplateGroupDao.saveAllRecordTemplateGroup(recordTemplateGroupPOList);
                List<RecordTemplateItemBO> recordTemplateItemBOList = groupList.stream().filter(e -> !CollectionUtils.isEmpty(e.getItemList()))
                        .peek(e -> e.getItemList().forEach(e1 -> {
                            e1.setRecordTemplateGroupId(e.getRecordTemplateGroupId());
                            e1.setRecordTemplateId(recordTemplatePO.getRecordTemplateId());
                        }))
                        .flatMap(e -> e.getItemList().stream())
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(recordTemplateItemBOList)) {
                    row += recordTemplateItemDao.saveAllRecordTemplateItem(RecordTemplateItemConverter.toPO(recordTemplateItemBOList));
                }
            }
        }
        return row;
    }

    @Override
    public int updateRecordTemplate(RecordTemplateBO recordTemplateBO) {
        return recordTemplateDao.updateRecordTemplate(RecordTemplateConverter.toPO(recordTemplateBO));
    }

    @Override
    public int deleteRecordTemplate(Long recordTemplateId) {
        return recordTemplateDao.deleteRecordTemplate(recordTemplateId);
    }

    @Override
    public RecordTemplateBO getRecordTemplate(RecordTemplateByIdQuery query) {
        RecordTemplateBO recordTemplateBO = RecordTemplateConverter.fromPO(recordTemplateDao.getRecordTemplate(query.getRecordTemplateId()));
        build(Collections.singletonList(recordTemplateBO), query.getWithGroup(), query.getWithItem());
        return recordTemplateBO;
    }

    @Override
    public RecordTemplateItemBO getRecordTemplateItem(Long recordTemplateItemId) {
        return RecordTemplateItemConverter.fromPO(recordTemplateItemDao.getRecordTemplateItem(recordTemplateItemId));
    }

    @Override
    public RecordTemplateGroupBO getRecordTemplateGroup(Long recordTemplateGroupId, Boolean withItem) {
        RecordTemplateGroupBO recordTemplateGroupBO = RecordTemplateGroupConverter.fromPO(recordTemplateGroupDao.getRecordTemplateGroup(recordTemplateGroupId));
        build(Collections.singletonList(recordTemplateGroupBO), withItem);
        return recordTemplateGroupBO;
    }

    @Override
    public List<RecordTemplateBO> listRecordTemplateById(Collection<Long> collection) {
        return RecordTemplateConverter.fromPO(recordTemplateDao.listRecordTemplateById(collection));
    }

    @Override
    public List<RecordTemplateBO> listRecordTemplate(RecordTemplateQuery query) {
        //build(query.getWithGroup(), recordTemplateBOList);
        return RecordTemplateConverter.fromPO(recordTemplateDao.listRecordTemplate(query));
    }

//    private void build(boolean withGroup, List<RecordTemplateBO> recordTemplateBOList) {
//        if (CollectionUtils.isEmpty(recordTemplateBOList)) {
//            return;
//        }
//        Set<Long> recordTemplateIdSet =
//                recordTemplateBOList.stream().map(RecordTemplateBO::getRecordTemplateId).collect(Collectors.toSet());
//        Map<Long, List<RecordTemplateGroupBO>> recordTemplateGroupMap = new HashMap<>();
//        if (withGroup) {
//            List<RecordTemplateGroupBO> recordTemplateGroupBOList = RecordTemplateGroupConverter.fromPO(recordTemplateGroupDao.listRecordTemplateGroupByTemplateIdList(recordTemplateIdSet));
//            if (!CollectionUtils.isEmpty(recordTemplateGroupBOList)) {
//                Map<Long, List<RecordTemplateItemBO>> recordTemplateItemMap = new HashMap<>();
//                Set<Long> groupIdSet = recordTemplateGroupBOList.stream().map(RecordTemplateGroupBO::getRecordTemplateGroupId).collect(Collectors.toSet());
//                recordTemplateItemMap.putAll(RecordTemplateItemConverter.fromPO(recordTemplateItemDao.listRecordTemplateItemByGroupId(groupIdSet))
//                        .stream().collect(Collectors.groupingBy(RecordTemplateItemBO::getRecordTemplateGroupId)));
//                recordTemplateGroupBOList.forEach(e -> {
//                    if (recordTemplateItemMap.containsKey(e.getRecordTemplateGroupId())) {
//                        e.setItemList(recordTemplateItemMap.get(e.getRecordTemplateGroupId()));
//                    }
//                });
//            }
//            recordTemplateGroupMap.putAll(recordTemplateGroupBOList
//                    .stream().collect(Collectors.groupingBy(RecordTemplateGroupBO::getRecordTemplateId)));
//        }
//        if (!CollectionUtils.isEmpty(recordTemplateGroupMap)) {
//            recordTemplateBOList.forEach(e -> {
//                if (recordTemplateGroupMap.containsKey(e.getRecordTemplateId())) {
//                    e.setGroupList(recordTemplateGroupMap.get(e.getRecordTemplateId()));
//                }
//            });
//        }
//    }

    @Override
    public int countRecordTemplate(RecordTemplateQuery query) {
        return recordTemplateDao.countRecordTemplate(query);
    }

    @Override
    public int saveRecordTemplateGroup(RecordTemplateGroupBO recordTemplateGroupBO) {
        RecordTemplateGroupPO recordTemplateGroupPO = RecordTemplateGroupConverter.toPO(recordTemplateGroupBO);
        int row = recordTemplateGroupDao.saveRecordTemplateGroup(recordTemplateGroupPO);
        if (row > 0) {
            List<RecordTemplateItemBO> itemList = recordTemplateGroupBO.getItemList();
            if (!CollectionUtils.isEmpty(itemList)) {
                itemList.forEach(e -> {
                    e.setRecordTemplateGroupId(recordTemplateGroupPO.getRecordTemplateGroupId());
                    e.setRecordTemplateId(recordTemplateGroupBO.getRecordTemplateId());
                });
                recordTemplateItemDao.saveAllRecordTemplateItem(RecordTemplateItemConverter.toPO(itemList));
            }
        }
        return row;
    }

    @Override
    public int updateRecordTemplateGroup(RecordTemplateGroupBO recordTemplateGroupBO) {
        return recordTemplateGroupDao.updateRecordTemplateGroup(RecordTemplateGroupConverter.toPO(recordTemplateGroupBO));
    }

    @Override
    public int updateAllRecordTemplateGroup(Collection<RecordTemplateGroupBO> collection) {
        return recordTemplateGroupDao.updateAllRecordTemplateGroup(RecordTemplateGroupConverter.toPO(collection));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int deleteRecordTemplateGroup(Pair<Long, Collection<RecordTemplateGroupBO>> data) {
        int row = recordTemplateGroupDao.deleteRecordTemplateGroup(data.getValue1());
        if (row > 0 && !CollectionUtils.isEmpty(data.getValue2())) {
            row += recordTemplateGroupDao.updateAllRecordTemplateGroup(RecordTemplateGroupConverter.toPO(data.getValue2()));
        }
        return row;
    }

    @Override
    public List<RecordTemplateGroupBO> listRecordTemplateGroupByTemplateId(Long recordTemplateId, boolean withItem) {
        List<RecordTemplateGroupBO> recordTemplateGroupBOList
                = RecordTemplateGroupConverter.fromPO(
                recordTemplateGroupDao.listRecordTemplateGroupByTemplateIdList(Collections.singletonList(recordTemplateId)));
        build(recordTemplateGroupBOList, withItem);
        return recordTemplateGroupBOList;
    }

    @Override
    public List<RecordTemplateGroupBO> groupRecordTemplateGroupByTemplateId(List<Long> recordTemplateIdList, boolean withItem) {
        List<RecordTemplateGroupBO> recordTemplateGroupBOList =
                RecordTemplateGroupConverter.fromPO(recordTemplateGroupDao.listRecordTemplateGroupByTemplateIdList(recordTemplateIdList));
        build(recordTemplateGroupBOList, withItem);
        return recordTemplateGroupBOList;
    }

    private void build(List<RecordTemplateBO> recordTemplateBOList, boolean withGroup, boolean withItem) {
        if (!CollectionUtils.isEmpty(recordTemplateBOList)) {
            return;
        }
        Set<Long> recordTemplateIdSet = recordTemplateBOList.stream()
                .map(RecordTemplateBO::getRecordTemplateId)
                .collect(Collectors.toSet());
        Map<Long, List<RecordTemplateGroupBO>> groupRecordTemplateGroup = new HashMap<>();
        if (withGroup) {
            List<RecordTemplateGroupBO> recordTemplateGroupBOList = RecordTemplateGroupConverter.fromPO(
                    recordTemplateGroupDao.listRecordTemplateGroupByTemplateIdList(new ArrayList<>(recordTemplateIdSet)));
            if (withItem) {
                build(recordTemplateGroupBOList, withItem);
            }
            groupRecordTemplateGroup.putAll(recordTemplateGroupBOList.stream()
                    .collect(Collectors.groupingBy(RecordTemplateGroupBO::getRecordTemplateId))
            );
        }
        recordTemplateBOList.forEach(e -> {
            if (groupRecordTemplateGroup.containsKey(e.getRecordTemplateId())) {
                e.setGroupList(groupRecordTemplateGroup.get(e.getRecordTemplateId()));
            }
        });
    }

    private void build(List<RecordTemplateGroupBO> recordTemplateGroupBOList, boolean withItem) {
        if (!withItem) {
            return;
        }
        if (CollectionUtils.isEmpty(recordTemplateGroupBOList)) {
            return;
        }
        Set<Long> recordTemplateGroupIdSet = recordTemplateGroupBOList.stream()
                .map(RecordTemplateGroupBO::getRecordTemplateGroupId)
                .collect(Collectors.toSet());
        Map<Long, List<RecordTemplateItemBO>> itemGroup = RecordTemplateItemConverter.fromPO(recordTemplateItemDao.listRecordTemplateItemByGroupId(recordTemplateGroupIdSet)).stream()
                .collect(Collectors.groupingBy(RecordTemplateItemBO::getRecordTemplateGroupId));
        if (CollectionUtils.isEmpty(itemGroup)) {
            return;
        }
        recordTemplateGroupBOList.forEach(e -> {
            if (itemGroup.containsKey(e.getRecordTemplateGroupId())) {
                e.setItemList(itemGroup.get(e.getRecordTemplateGroupId()));
            }
        });

    }

    @Override
    public List<RecordTemplateItemBO> listRecordTemplateItemByGroupId(Long recordTemplateGroupId) {
        return RecordTemplateItemConverter.fromPO(recordTemplateItemDao.listRecordTemplateItemByGroupId(Arrays.asList(recordTemplateGroupId)));
    }

    @Override
    public int saveRecordTemplateItem(RecordTemplateItemBO recordTemplateItemBO) {
        return recordTemplateItemDao.saveRecordTemplateItem(RecordTemplateItemConverter.toPO(recordTemplateItemBO));
    }

    @Override
    public int updateRecordTemplateItem(RecordTemplateItemBO recordTemplateItemBO) {
        return recordTemplateItemDao.updateRecordTemplateItem(RecordTemplateItemConverter.toPO(recordTemplateItemBO));
    }

    @Override
    public int updateAllRecordTemplateItem(Collection<RecordTemplateItemBO> collection) {
        return recordTemplateItemDao.updateAllRecordTemplateItem(RecordTemplateItemConverter.toPO(collection));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int deleteRecordTemplateItem(Pair<Long, Collection<RecordTemplateItemBO>> data) {
        int row = recordTemplateItemDao.deleteRecordTemplateItem(data.getValue1());
        if (row > 0 && !CollectionUtils.isEmpty(data.getValue2())) {
            row += recordTemplateItemDao.updateAllRecordTemplateItem(RecordTemplateItemConverter.toPO(data.getValue2()));
        }
        return row;
    }

}
